package cn.jasonone.jfx.manager;

import cn.hutool.core.util.ReflectUtil;
import cn.jasonone.jfx.config.properties.JfxProperties;
import cn.jasonone.jfx.context.BaseController;
import cn.jasonone.jfx.factory.StageFactory;
import cn.jasonone.jfx.mananger.SceneManager;
import cn.jasonone.jfx.mananger.StageManager;
import cn.jasonone.jfx.util.NodeUtil;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Set;

/**
 * 舞台管理器
 *
 * @author xujie
 * @version 1.0
 * @date 2021/12/21 14:12
 */
@Component("stageManager")
public class JfxStageManager implements StageManager, InitializingBean {
    public static final String PRIMARY_STAGE_KEY = "PRIMARY";
    @Resource
    private StageFactory stageFactory;
    @Resource
    private SceneManager sceneManager;
    @Resource
    private NodeUtil nodeUtil;
    @Resource
    private JfxProperties jfxProperties;

    @Override
    public Stage getPrimaryStage() {
        Scene scene = sceneManager.getPrimaryScene();
        Stage stage = stageFactory.getStage(PRIMARY_STAGE_KEY, jfxProperties.getTitle() + " - v" + jfxProperties.getVersion());
        bindScene(stage, scene);
        return stage;
    }

    @Override
    public void bindScene(Stage stage, Scene scene) {
        if (stage.getScene() != null) {
            update(null, stage, stage.getScene());
        }
        stage.setScene(scene);
        update(stage, null, scene);
    }

    @Override
    public Stage createStage(Class controllerType, String title) throws Exception {
        Scene scene = sceneManager.createScene(controllerType);
        Stage stage = stageFactory.getStage(controllerType.getName(), title);
        bindScene(stage, scene);
        return stage;
    }


    private void update(Stage stage, Stage oldStage, Scene scene) {
        Parent rootParent = sceneManager.getRootParent(scene);
        // 更新场景中所有节点的舞台数据
        Set<BaseController> controllers = nodeUtil.getControllers(rootParent, c -> c instanceof BaseController);
        for (BaseController controller : controllers) {
            ReflectUtil.setFieldValue(controller, "stage", stage);
            ReflectUtil.setFieldValue(controller, "scene", scene);
            if (stage == null) {
                controller.removeStage(oldStage);
            } else {
                controller.addStage(stage);
            }
        }
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        this.sceneManager.setStageManager(this);
    }
}
